package OfferLanQiaoBei;
/*
小蓝最近迷上了一款电玩游戏“蓝桥争霸”。
这款游戏由很多关卡和副本组成，每一关可以抽象为一个节点，整个游戏的关卡可以抽象为一棵树形图，
每一关会有一道算法题，只有当经验值不低于第 i 关的要求 ki 时，小蓝才能挑战成功通过此关，并且获得 si 的经验值，每关的经验值只能获得一次。
每个关卡（除了 1 号点），都会有一个前置关卡，只有通过了前置关卡，才能挑战后续关卡。

小蓝初始在 1 号点，也就是游戏开局初始点，同时具有一个初始经验值 P，他可以任意规划挑战顺序，他想问你最多能够挑战成功多少道题。
小蓝会告诉你关卡的所有信息，以及他的初始经验值，你需要回答他最多能够挑战成功多少关卡。
输入格式
第一行输入两个整数 n,P，表示关卡的数量以及小蓝的初始经验值。
接下来 n 行，每行输入三个整数 fi,si,ki，
fi 表示每一关的前置关卡（ f1 一定为 0 ），si 表示经验值，ki 表示挑战成功最少需要的经验值。
输出格式
一个整数，表示在最优的规划下，最多能挑战成功的关卡数量。
样例输入
4 5
0 3 5
1 2 8
1 3 9
3 1 15
样例输出
3
现在有一种解法是，解释这种解法：
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.HashMap;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
static int N = 100005;
static long n, P;
static Node[] node = new Node[N];
static PriorityQueue<Node> q = new PriorityQueue<>(new Comparator<Node>() {
public int compare(Node a, Node b) {
return a.k > b.k ? 1 : -1;
}
});
static ArrayList<Integer>[] G = new ArrayList[N];

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    n = scan.nextLong();
    P = scan.nextLong();

    for (int i = 0; i < N; i++) {
        G[i] = new ArrayList<Integer>();
    }

    for (int i = 1; i <= n; i++) {
        long u, s, k;
        u = scan.nextLong();
        s = scan.nextLong();
        k = scan.nextLong();
        G[(int)u].add(i);
        node[i] = new Node(s, k, i);
    }

    long ans = 0;

    for (int i = 0; i < G[0].size(); i++) {
        int ch = G[0].get(i);
        q.offer(node[ch]);
    }

    while (!q.isEmpty()) {
        Node t = q.poll();
        if (P >= t.k) {
            P += t.s;
            ans++;
            for (int i = 0; i < G[t.id].size(); i++) {
                int ch = G[t.id].get(i);
                q.offer(node[ch]);
            }
        }
    }

    System.out.println(ans);
}

static class Node {
    long s = 0, k = 0, id = 0;

    public Node(long s, long k, long id) {
        this.s = s;
        this.k = k;
        this.id = id;
    }
}

}
 */


import java.util.*;

public class Main4 {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        /*
        这是优先队列
        新元素的首element > 旧元素的首element，则插入旧元素后面
        也就是说，新元素的攻克需要的经验值 > 旧元素的攻克需要的经验值，新元素排在旧元素后面；这句话需要看懂后面的代码才能看明白
         */
        PriorityQueue<Integer[]> queue = new PriorityQueue<>(
                //这里使用lambda表达式
                (a, b) -> (a[0] - b[0])
        );
        int n = scan.nextInt();
        int currentExp = scan.nextInt();
        /*
        “索引+1”代表”第几关“
        索引上的元素singleList的size()代表：第“索引+1”关的后面有size()个可以被挑战的关
        singleList的每个元素的值存储的是expList，needList的索引
         */
        List<Integer>[] pp = new ArrayList[n];
        //把数组的每一个元素都初始化
        Arrays.setAll(pp, e -> new ArrayList<>());

        //每关奖励的经验值
        List<Integer> expList = new ArrayList<>();
        //每关需要的经验值
        List<Integer> needList = new ArrayList<>();

        //吃掉数据的第一行的首元素,因为是0
        scan.nextInt();
        /*
        “索引+1”代表”第几关“
        数据的第一行的剩下的两个元素放入对应的集合，注意添加元素是从索引0开始添加
        这两个集合的“索引+1”的含义是“第几关”
         */
        expList.add(scan.nextInt());
        needList.add(scan.nextInt());

        //定义结果
        int ans = 0;
        if (currentExp < needList.get(0)) {
            //如果初始经验不足以打通第1关，则直接返回“通过了0关”
            System.out.println(ans);
            return;
        }
        //如果初始经验足以打通第1关，则保存这次通关结果
        currentExp += expList.get(0);
        ans++;
        //开始判断后续的通关过程
        for (int i = 1; i < n; i++) {
            //“i+1”代表“第几关”
            int preId = scan.nextInt();
            int exp = scan.nextInt();
            int need = scan.nextInt();
            //此时expList添加元素的索引，应该恰好和i一致
            expList.add(exp);
            needList.add(need);
            //singleList的每个元素的值存储的是expList，needList的索引
            pp[preId - 1].add(i);
        }
        //对于第一关，把第一关后面的所有直接相连的关，入队列
        for (int i : pp[0]) {
            queue.offer(//会根据我们自定义的规则进行“旋转排序”存入队列的元素
                    new Integer[]{
                            //攻克此直接相连的关需要的经验
                            needList.get(i),
                            //此直接相连的关对应在expList，needList中的索引；“i+1”代表“第几关”
                            i
                    }
            );
        }

        while (!queue.isEmpty()) {
            Integer[] poll = queue.poll();
            //如果优先队列的弹出的出队元素都无法被攻克，那该元素后面的元素肯定都无法被攻克；充分利用优先队列特性
            Integer need = poll[0];
            if (currentExp < need) {
                System.out.println(ans);
                return;
            }

            //到这里，确认攻克了poll代表的关；“index+1”代表“第几关”
            Integer index = poll[1];
            currentExp += expList.get(index);
            //获取攻克了的poll关后面的直接相连关
            List<Integer> nextRooms = pp[index];
            ans++;
            for (int i : nextRooms) {
                //因为随着关越来越多，need也越来越高，所以越晚添加进队列的元素，越不再会可能被“旋转排序”
                queue.offer(
                        new Integer[]{
                                //攻克此直接相连的关需要的经验
                                needList.get(i),
                                //此直接相连的关对应在expList，needList中的索引；“i+1”代表“第几关”
                                i
                        }
                );
            }
        }
        System.out.println(ans);
        scan.close();
    }

}